From 1a488277536c30ac085ef0a89be8fb16ad44995c Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Thu, 1 Mar 2007 11:21:44 -0700 Subject: [PATCH] [IA64] Handle MMIO EFI mappings outside the page table range We cannot rely on MMIO pages presented in the EFI mem-map can be mapped directly to the same meta-physical address, because of restrictions on the address range imposed by the page tables. As an example, IO ports are located at 0x1ffffffffc000000 on many SN2 systems. Change assign_domain_mmio_page() to take a flags and a source and destination address to handle this and catch IO ports above 0x1ffffffff0000000 and map them down to a safe area. Signed-off-by: Jes Sorensen --- xen/arch/ia64/xen/dom0_ops.c | 6 +++++- xen/arch/ia64/xen/dom_fw.c | 23 ++++++++++++++++++++--- xen/arch/ia64/xen/mm.c | 13 ++++++++++--- xen/include/asm-ia64/mm.h | 2 +- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/xen/arch/ia64/xen/dom0_ops.c b/xen/arch/ia64/xen/dom0_ops.c index 52c3745f87..d20170150f 100644 --- a/xen/arch/ia64/xen/dom0_ops.c +++ b/xen/arch/ia64/xen/dom0_ops.c @@ -299,13 +299,17 @@ dom0vp_ioremap(struct domain *d, unsigned long mpaddr, unsigned long size) if (size == 0) size = PAGE_SIZE; + if (size == 0) + printk(XENLOG_WARNING "ioremap(): Trying to map %lx, size 0\n", mpaddr); + end = PAGE_ALIGN(mpaddr + size); if (!iomem_access_permitted(d, mpaddr >> PAGE_SHIFT, (end >> PAGE_SHIFT) - 1)) return -EPERM; - return assign_domain_mmio_page(d, mpaddr, size); + return assign_domain_mmio_page(d, mpaddr, mpaddr, size, + ASSIGN_writable | ASSIGN_nocache); } unsigned long diff --git a/xen/arch/ia64/xen/dom_fw.c b/xen/arch/ia64/xen/dom_fw.c index c69ab89c80..7402d3f77b 100644 --- a/xen/arch/ia64/xen/dom_fw.c +++ b/xen/arch/ia64/xen/dom_fw.c @@ -534,6 +534,7 @@ complete_dom0_memmap(struct domain *d, u64 start = md->phys_addr; u64 size = md->num_pages << EFI_PAGE_SHIFT; u64 end = start + size; + u64 mpaddr; unsigned long flags; switch (md->type) { @@ -566,10 +567,22 @@ complete_dom0_memmap(struct domain *d, break; case EFI_MEMORY_MAPPED_IO_PORT_SPACE: + flags = ASSIGN_writable; /* dummy - zero */ + if (md->attribute & EFI_MEMORY_UC) + flags |= ASSIGN_nocache; + + if (start > 0x1ffffffff0000000UL) { + mpaddr = 0x4000000000000UL - size; + printk(XENLOG_INFO "Remapping IO ports from " + "%lx to %lx\n", start, mpaddr); + } else + mpaddr = start; + /* Map into dom0. */ - assign_domain_mmio_page(d, start, size); + assign_domain_mmio_page(d, mpaddr, start, size, flags); /* Copy descriptor. */ *dom_md = *md; + dom_md->phys_addr = mpaddr; dom_md->virt_addr = 0; num_mds++; break; @@ -652,8 +665,12 @@ complete_dom0_memmap(struct domain *d, if (domain_page_mapped(d, addr)) continue; - if (efi_mmio(addr, PAGE_SIZE)) - assign_domain_mmio_page(d, addr, PAGE_SIZE); + if (efi_mmio(addr, PAGE_SIZE)) { + unsigned long flags; + flags = ASSIGN_writable | ASSIGN_nocache; + assign_domain_mmio_page(d, addr, addr, + PAGE_SIZE, flags); + } } return num_mds; } diff --git a/xen/arch/ia64/xen/mm.c b/xen/arch/ia64/xen/mm.c index b1efa6293f..9ce2c34949 100644 --- a/xen/arch/ia64/xen/mm.c +++ b/xen/arch/ia64/xen/mm.c @@ -1044,9 +1044,11 @@ efi_mmio(unsigned long physaddr, unsigned long size) } unsigned long -assign_domain_mmio_page(struct domain *d, - unsigned long mpaddr, unsigned long size) +assign_domain_mmio_page(struct domain *d, unsigned long mpaddr, + unsigned long phys_addr, unsigned long size, + unsigned long flags) { + unsigned long end = PAGE_ALIGN(mpaddr + size); if (size == 0) { gdprintk(XENLOG_INFO, "%s: domain %p mpaddr 0x%lx size = 0x%lx\n", __func__, d, mpaddr, size); @@ -1058,7 +1060,12 @@ assign_domain_mmio_page(struct domain *d, #endif return -EINVAL; } - assign_domain_same_page(d, mpaddr, size, ASSIGN_writable | ASSIGN_nocache); + + for (mpaddr &= PAGE_MASK; mpaddr < end; + mpaddr += PAGE_SIZE, phys_addr += PAGE_SIZE) { + __assign_domain_page(d, mpaddr, phys_addr, flags); + } + return mpaddr; } diff --git a/xen/include/asm-ia64/mm.h b/xen/include/asm-ia64/mm.h index a232bd599c..944775aae5 100644 --- a/xen/include/asm-ia64/mm.h +++ b/xen/include/asm-ia64/mm.h @@ -433,7 +433,7 @@ struct p2m_entry; extern unsigned long lookup_domain_mpa(struct domain *d, unsigned long mpaddr, struct p2m_entry* entry); extern void *domain_mpa_to_imva(struct domain *d, unsigned long mpaddr); extern volatile pte_t *lookup_noalloc_domain_pte(struct domain* d, unsigned long mpaddr); -extern unsigned long assign_domain_mmio_page(struct domain *d, unsigned long mpaddr, unsigned long size); +extern unsigned long assign_domain_mmio_page(struct domain *d, unsigned long mpaddr, unsigned long phys_addr, unsigned long size, unsigned long flags); extern unsigned long assign_domain_mach_page(struct domain *d, unsigned long mpaddr, unsigned long size, unsigned long flags); int domain_page_mapped(struct domain *d, unsigned long mpaddr); int efi_mmio(unsigned long physaddr, unsigned long size); -- 2.30.2